home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Snippets / Stuart's Tech Notes / StUU / Sources / DSUtils.c < prev    next >
Text File  |  1995-11-30  |  12KB  |  394 lines

  1. /******************************************************************************
  2. **
  3. **  Project Name:    DropShell
  4. **     File Name:    DSUtils.c
  5. **
  6. **   Description:    Utility routines that may be useful to DropBoxes
  7. **
  8. *******************************************************************************
  9. **                       A U T H O R   I D E N T I T Y
  10. *******************************************************************************
  11. **
  12. **    Initials    Name
  13. **    --------    -----------------------------------------------
  14. **    SCS            Stephan Somogyi
  15. **    LDR            Leonard Rosenthol
  16. **
  17. *******************************************************************************
  18. **                      R E V I S I O N   H I S T O R Y
  19. *******************************************************************************
  20. **
  21. **      Date        Author    Description
  22. **    ---------    ------    ---------------------------------------------
  23. **    23 Jun 94    LDR        Added a bunch of new routines for Marshall
  24. **    20 Feb 94    LDR        Added some new useful File System routines
  25. **    11 Dec 93    SCS        Universal Headers/UPPs (Phoenix 68k/PPC & PPCC)
  26. **                        Skipped System 6 compatible rev of DropShell source
  27. **                        Changed GetAppName to GetMyAppName (StdCLib conflict)
  28. **    12/09/91    LDR        Added the Apple event routines
  29. **    11/24/91    LDR        Original Version
  30. **
  31. ******************************************************************************/
  32.  
  33. #include <Dialogs.h>
  34. #include <Types.h>
  35.  
  36. #include "DSGlobals.h"
  37. #include "DSUtils.h"
  38.  
  39. /*
  40.     This routine is used to properly center an Alert before showing.
  41.     
  42.     It is per Human Interface specs by putting it in the top 1/3 of screen.
  43.     NOTE: This same technique can be used with DLOG resources as well.
  44. */
  45. #pragma segment Main
  46. void CenterAlert ( short theID ) {
  47. theID;    // Unused
  48. // Actually, don't do this -- the second time any particular alert is displayed,
  49. // CenterAlert moves it right off the screen, which is a bit disconcerting
  50. /*
  51.     short        theX, theY;
  52.     AlertTHndl    theAlertHandle;
  53.     Rect        screen, alrt;
  54.     
  55.     theAlertHandle = (AlertTHndl) GetResource ( 'ALRT', theID );
  56.     if ( theAlertHandle != NULL ) {
  57.         HLock ((Handle) theAlertHandle );
  58.  
  59.         alrt = (*theAlertHandle)->boundsRect;
  60.         screen = qd.screenBits.bounds;
  61.         
  62.         theX = (( screen.right - screen.left ) - (alrt.right - alrt.left )) >> 1;
  63.         theY = (( screen.bottom - screen.top ) + GetMBarHeight () - (alrt.bottom - alrt.top)) >> 1;
  64.         theY -= ( screen.bottom - screen.top ) >> 2;    // this moves it up for better viewing!
  65.         OffsetRect ( &(*theAlertHandle)->boundsRect, theX - alrt.left, theY - alrt.top );
  66.     }
  67. */        
  68.     SetCursor ( &qd.arrow );    // change this for code resources!
  69. }
  70.  
  71. /*
  72.     This routine is just a quick & dirty error reporter
  73. */
  74. #pragma segment Main
  75. void ErrorAlert ( short stringListID, short stringIndexID, short errorID ) {
  76.     #define    kAlertID    200
  77.     Str255    param, errorStr;
  78.     
  79.     NumToString ( errorID, errorStr );
  80.     GetIndString ( param, stringListID, stringIndexID );
  81.     ParamText ( param,  errorStr, NULL, NULL );
  82.     CenterAlert ( kAlertID );
  83.     (void) Alert ( kAlertID, NULL );
  84. }
  85.  
  86. /*** These routines use the Process Manager to give you information about yourself ***/
  87.  
  88. #pragma segment Main
  89. void GetMyAppName(Str255 appName)    {
  90.     OSErr                err;
  91.     ProcessInfoRec        info;
  92.     ProcessSerialNumber    curPSN;
  93.  
  94.     err = GetCurrentProcess(&curPSN);
  95.     
  96.     info.processInfoLength = sizeof(ProcessInfoRec);    // ALWAYS USE sizeof!
  97.     info.processName = appName;                            // so it returned somewhere
  98.     info.processAppSpec = NULL;                            // I don't care!
  99.  
  100.     err = GetProcessInformation(&curPSN, &info);
  101. }
  102.  
  103. #pragma segment Main
  104. void GetAppFSSpec(FSSpec *appSpec)    {
  105.     OSErr                err;
  106.     Str255                appName;
  107.     ProcessInfoRec        info;
  108.     ProcessSerialNumber    curPSN;
  109.  
  110.     err = GetCurrentProcess(&curPSN);
  111.     
  112.     info.processInfoLength = sizeof(ProcessInfoRec);    // ALWAYS USE sizeof!
  113.     info.processName = appName;                            // so it returned somewhere
  114.     info.processAppSpec = appSpec;                        // so it can get returned!
  115.  
  116.     err = GetProcessInformation(&curPSN, &info);
  117. }
  118.  
  119. /* ••• File Routines begin here ••• */
  120. /*
  121.     This routine is used to force the Finder (as much as is possible) to update
  122.     information about a newly changed file or folder.  
  123.     It does this by changing the modification date of the surrounding folder.
  124. */
  125. OSErr ForceFinderUpdate(FSSpec *pFSS, Boolean flush)
  126. {
  127.     OSErr            lErr;
  128.     CInfoPBRec        lCBlk;
  129.     
  130.     if (pFSS->parID != 1)                            // if it's a vol then reuse the NameStr
  131.         lCBlk.dirInfo.ioNamePtr = 0L;
  132.     lCBlk.dirInfo.ioVRefNum = pFSS->vRefNum;        
  133.     lCBlk.dirInfo.ioDrDirID = pFSS->parID;
  134.     lCBlk.dirInfo.ioFDirIndex = 0;
  135.     lCBlk.dirInfo.ioCompletion = 0;
  136.  
  137.     lErr = PBGetCatInfoSync(&lCBlk);
  138.     if (!lErr) {
  139.         GetDateTime(&lCBlk.dirInfo.ioDrMdDat);
  140.         lCBlk.dirInfo.ioDrDirID = pFSS->parID;
  141.         lErr = PBSetCatInfoSync(&lCBlk);
  142.     
  143.         if ((!lErr) && (flush))
  144.             lErr = FlushVol(nil, pFSS->vRefNum);
  145.     }
  146.     
  147.     return (lErr);
  148. }
  149.  
  150. /*    Is the file in use (busy)? */
  151. Boolean FSpIsBusy(FSSpecPtr theFile)
  152. {
  153.     Boolean        isBusy = false;
  154.     OSErr        err;
  155.     CInfoPBRec    cipb;
  156.     
  157.     cipb.hFileInfo.ioCompletion    = 0L;
  158.     cipb.hFileInfo.ioNamePtr    = theFile->name;
  159.     cipb.hFileInfo.ioVRefNum    = theFile->vRefNum;
  160.     cipb.hFileInfo.ioFDirIndex    = 0;
  161.     cipb.hFileInfo.ioDirID        = theFile->parID;
  162.     err = PBGetCatInfoSync(&cipb);
  163.     if (!err) {
  164.         isBusy = (cipb.hFileInfo.ioFlAttrib & 0x80) == 0x80;    // bit 7 = either fork open
  165.     }
  166.     return(isBusy);
  167. }
  168.  
  169. /*    Is the “file” represented by this FSSpec really a folder? */
  170. Boolean    FSpIsFolder (FSSpecPtr theFSSpec) 
  171. {
  172.     OSErr    err;
  173.     CInfoPBRec    pb;
  174.     Str255    fName;
  175.     
  176.     if (theFSSpec->parID == fsRtParID)    // it's a volume!!
  177.         return(true);
  178.         
  179.     BlockMoveData (theFSSpec->name, fName, 32);
  180.     pb.hFileInfo.ioDirID        = theFSSpec->parID;
  181.     pb.hFileInfo.ioCompletion    = NULL;
  182.     pb.hFileInfo.ioNamePtr        = fName;
  183.     pb.hFileInfo.ioVRefNum        = theFSSpec->vRefNum;
  184.     pb.hFileInfo.ioFDirIndex    = 0;
  185.     pb.hFileInfo.ioFVersNum        = 0;
  186.     err = PBGetCatInfoSync(&pb);
  187.     
  188.     if (!err) {
  189.         if (pb.hFileInfo.ioFlAttrib & ioDirMask)
  190.             return(true);
  191.     }
  192.     return(false);
  193. }
  194.  
  195. // Creates an empty handle to which FSSpecs could be added later!
  196. FSSpecArrayHandle    NewFSSpecList(void)
  197. {
  198.     return((FSSpecArrayHandle)NewHandle(0));
  199. }
  200.  
  201. // Releases memory used by an FSSpecList when all done
  202. void DisposeFSSpecList(FSSpecArrayHandle fsList)
  203. {
  204.     DisposHandle((Handle)fsList);
  205. }
  206.  
  207. // Adds the new FSSpec to the end of an FSSpecList
  208. void AddToFSSpecList(FSSpec *fSpec, FSSpecArrayHandle fileList)
  209. {
  210.     Size    curSize, newSize;
  211.     long    numFiles;
  212.  
  213.     if ((!fileList) || (!fSpec)) return;    // if either is bogus, get out fast
  214.     
  215.     curSize = GetHandleSize((Handle)fileList);
  216.     numFiles = curSize / sizeof(FSSpec);
  217.     newSize = curSize + sizeof(FSSpec);
  218.     SetHandleSize((Handle)fileList, newSize);
  219.     if (MemError())    return;        // any problems, get out
  220.     
  221.     BlockMove(fSpec, &(*fileList)[numFiles], sizeof(FSSpec));
  222. }
  223.  
  224.  
  225. /* ••• Apple event routines begin here ••• */
  226.  
  227. /*
  228.     This routine will create a targetDesc for sending to self.
  229.  
  230.     We take IM VI's advice and use the typePSN form with 
  231.     kCurrentProcess as the targetPSN.
  232. */
  233. OSErr GetTargetFromSelf (AEAddressDesc *targetDesc)
  234. {
  235.     ProcessSerialNumber    psn;
  236.  
  237.     psn.highLongOfPSN     = 0;
  238.     psn.lowLongOfPSN     = kCurrentProcess;
  239.  
  240.     return( AECreateDesc(typeProcessSerialNumber, (Ptr)&psn, sizeof(ProcessSerialNumber), targetDesc) );
  241. }
  242.  
  243. /* This routine will create a targetDesc using the apps signature */
  244. OSErr GetTargetFromSignature (OSType processSig, AEAddressDesc *targetDesc)
  245. {
  246.     return( AECreateDesc(typeApplSignature, (Ptr)&processSig, sizeof(processSig), targetDesc) );
  247. }
  248.  
  249. /* This routine will create a targetDesc by bringing up the PPCBrowser */
  250. OSErr GetTargetFromBrowser(Str255 promptStr, AEAddressDesc *targetDesc)
  251. {
  252.     OSErr        err;
  253.     TargetID    theTarget;
  254.     PortInfoRec    portInfo;
  255.     
  256.     err = PPCBrowser(promptStr, "\p", false, &theTarget.location, &portInfo, NULL, "\p");
  257.     if (err == noErr) {
  258.         theTarget.name = portInfo.name;
  259.         err = AECreateDesc(typeTargetID, (Ptr)&theTarget, sizeof(TargetID), targetDesc);
  260.     }
  261.     return( err );
  262. }
  263.  
  264.  
  265. /*
  266.     This routine is the low level routine used by the SendODOCToSelf
  267.     routine.  It gets passed the list of files (in an AEDescList)
  268.     to be sent as the data for the 'odoc', builds up the event
  269.     and sends off the event.  
  270.  
  271.     It is broken out from SendODOCToSelf so that a SendODOCListToSelf could
  272.     easily be written and it could then call this routine - but that is left
  273.     as an exercise to the reader.
  274.     
  275.     Read the comments in the code for the order and details
  276. */
  277. void _SendDocsToSelf (AEDescList *aliasList)
  278. {
  279.     OSErr            err;
  280.     AEAddressDesc    theTarget;
  281.     AppleEvent        openDocAE, replyAE;
  282.  
  283. /*
  284.     First we create the target for the event.   We call another
  285.     utility routine for creating the target.
  286. */
  287.     err = GetTargetFromSelf(&theTarget);
  288.     if (err == noErr) {
  289.         /* Next we create the Apple event that will later get sent. */
  290.         err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &theTarget, kAutoGenerateReturnID, kAnyTransactionID, &openDocAE);
  291.  
  292.         if (err == noErr) {
  293.             /* Now add the aliasDescList to the openDocAE */
  294.             err = AEPutParamDesc(&openDocAE, keyDirectObject, aliasList);
  295.  
  296.             if (err == noErr) {
  297.                 /*
  298.                     and finally send the event
  299.                     Since we are sending to ourselves, no need for reply.
  300.                 */
  301.                 err = AESend(&openDocAE, &replyAE, kAENoReply + kAECanInteract, kAENormalPriority, 3600, NULL, NULL);
  302.  
  303.                 /*
  304.                     NOTE: Since we are not requesting a reply, we do not need to
  305.                     need to dispose of the replyAE.  It is there simply as a 
  306.                     placeholder.
  307.                 */
  308.             }
  309.  
  310.         /*    
  311.             Dispose of the aliasList descriptor
  312.             We do this instead of the caller since it needs to be done
  313.             before disposing the AEVT
  314.         */
  315.             err = AEDisposeDesc(aliasList);
  316.         }
  317.  
  318.     /*and of course dispose of the openDoc AEVT itself*/
  319.         err = AEDisposeDesc(&openDocAE);
  320.     }
  321. }
  322.  
  323. /*
  324.     This is the routine called by SelectFile to send a single odoc to ourselves.
  325.     
  326.     It calls the above low level routine to do the dirty work of sending the AEVT -
  327.     all we do here is build a AEDescList of the file to be opened.
  328. */
  329. void SendODOCToSelf (FSSpec *theFileSpec) {
  330.  
  331.     OSErr        err;
  332.     AEDescList    aliasList;
  333.     AEDesc        aliasDesc;
  334.     AliasHandle    aliasH;
  335.     
  336.     /*Create the descList to hold the list of files*/
  337.     err = AECreateList(NULL, 0, false, &aliasList);
  338.  
  339.     if (err == noErr) {
  340.         /* First we setup the type of descriptor */
  341.         aliasDesc.descriptorType = typeAlias;
  342.  
  343.         /*
  344.             Now we add the file to descList by creating an alias and then
  345.             adding it into the descList using AEPutDesc
  346.         */
  347.         err = NewAlias(NULL, theFileSpec, &aliasH);
  348.         aliasDesc.dataHandle = (Handle)aliasH;
  349.         err = AEPutDesc(&aliasList, 0, &aliasDesc);
  350.         DisposHandle((Handle)aliasH);
  351.  
  352.         /*Now call the real gut level routine to do the dirty work*/
  353.         _SendDocsToSelf(&aliasList);
  354.  
  355.         /*_SendDocsToSelf will dispose of aliasList for me*/
  356.     }
  357. }
  358.  
  359.  
  360. void SendQuitToSelf (void)
  361. {
  362.     OSErr            err;
  363.     AEAddressDesc    theTarget;
  364.     AppleEvent        quitAE, replyAE;
  365.  
  366. /*
  367.     First we create the target for the event.   We call another
  368.     utility routine for creating the target.
  369. */
  370.     err = GetTargetFromSelf(&theTarget);
  371.     if (err == noErr) {
  372.         /* Next we create the Apple event that will later get sent. */
  373.         err = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theTarget, kAutoGenerateReturnID, kAnyTransactionID, &quitAE);
  374.  
  375.         if (err == noErr) {
  376.             /*
  377.                 and finally send the event
  378.                 Since we are sending to ourselves, no need for reply.
  379.             */
  380.             err = AESend(&quitAE, &replyAE, kAENoReply + kAECanInteract, kAENormalPriority, 3600, NULL, NULL);
  381.  
  382.             /*
  383.                 NOTE: Since we are not requesting a reply, we do not need to
  384.                 need to dispose of the replyAE.  It is there simply as a 
  385.                 placeholder.
  386.             */
  387.         }
  388.  
  389.         /* and of course dispose of the quit AEVT itself */
  390.         err = AEDisposeDesc(&quitAE);
  391.     }
  392. }
  393.  
  394.